global generar_codificacion

;int generar_codificacion ( unsigned char *src_buf, unsigned int src_size,
;	unsigned char *dst_buf, unsigned int dst_size, codigo_t *tabla_codigos )

extern printf

%define p_src_buf ebp+8
%define src_size ebp+12
%define p_dst_buf ebp+16
%define dst_size ebp+20
%define p_tabla_codigos ebp+24
%define tam_codigo_t 16
%define error -1

%define offset_codigo 0
%define offset_codigo_rev 4
%define offset_long_codigo 8
%define offset_valido 12 

%define bits_disponibles ebp-16
%define proxSimbolo ebp-12
%define long_codigo ebp-8
%define codigo ebp-4

%define null 0

 

section .data

error_src_buf: db 'ERROR: El buffer de ORIGEN no puede ser null',10,0
error_dst_buf: db 'ERROR: El buffer de DESTINO no puede ser null',10,0
error_codificacion: db 'ERROR GRAVE: No se puede codificar el simbolo',10,0


section .text
generar_codificacion:
	;enter 16,0   ;comentado para probar con valgrind
	push ebp
	mov ebp,esp
	sub esp,16
	
	push ebx
	push esi
	push edi

	
	mov ebx, [p_src_buf] ; en ebx tengo el puntero al buffer a comprimir
	mov esi, [src_size] ; tengo el tamanio del buffer a codificar
	mov edi, [p_dst_buf] ; en edi tengo el puntero al buffer de destino.
	
	cmp ebx,null
	jne _verificarDestino

_error_src_buf:
	push error_src_buf
	call printf
	add esp,4
	mov eax, error
	jmp  fin	
	
	
_verificarDestino:
	cmp edi,null
	jne _comenzar

_error_dst_buf:
	push error_dst_buf
	call printf
	add esp,4
	mov eax,error
	jmp fin
	
		
_comenzar:
	xor ecx,ecx
	mov dword [bits_disponibles], 32
	
	mov [proxSimbolo],ebx
	xor ebx,ebx
	
	
_recorrer_src_buf:
	cmp esi,0
	jne _siguienteSimbolo
	xor eax, eax ; pongo en cero eax para devolver que la funcion no dio error.
	jmp _volcarUltimosBits
	

	
_siguienteSimbolo:
	xor edx,edx
	mov eax, [proxSimbolo]
	mov dl,[eax] ; en edx tenemos el simbolo a codificar.

	
	shl edx,4  ; multiplico por 16 (tamanio de la estructura) 
	
	add edx, [p_tabla_codigos] ; me posiciono en la posicion edx de la tabla de codigos
	
	cmp dword [edx+offset_valido] ,0 ;
	jne _codificar 
	
_error_codificacion:
	push error_codificacion
	call printf 
	add esp,4
	mov eax,error
	
	jmp fin

_codificar:
	
	mov eax, [edx+offset_codigo]
	mov dword [codigo],eax   ; guardamos en una variable local el codigo
	
	mov eax, [edx+offset_long_codigo]
	mov dword [long_codigo],eax ; guardamos en una variable local la longitud del codigo
	
	
	mov ecx,[bits_disponibles]
	
	cmp [long_codigo],ecx ; comparo el espacio libre del registro "buffer" con la log del codigo actual
	jge _noSobra
	
	
_entraYSobra:
	sub ecx,[long_codigo]	
	mov eax, [codigo]
	shl eax,cl	; shifteamos el codigo actual al lugar donde lo vamos a guardar en ebx (reg buffer)
	or ebx,eax	; copiamos el codigo en el lugar correcto de ebx
	mov [bits_disponibles],ecx
	jmp _continuar
	
_noSobra:
	mov eax, [codigo]
	cmp ecx,[long_codigo]
	
	jne _noEntraJusto
	
	or ebx,eax	; copiamos el codigo en el lugar correcto de ebx
	mov dword [bits_disponibles],32
	bswap ebx	; Invertimos para que nos respete el orden de los bits
	mov [edi],ebx
	add edi,4
	xor ebx,ebx
	jmp _continuar	
	
_noEntraJusto:
	
	mov ecx,[long_codigo]
	sub ecx,[bits_disponibles] ; en ecx queda la logintud de los bits sobrantes.
	
	shr eax,cl
	or ebx,eax	; copiamos el codigo en el lugar correcto de ebx
	
	bswap ebx	; Invertimos para que nos respete el orden de los bits
	mov [edi],ebx	; copiamos el contenido del registro buffer al buffer de destino.
	add edi,4	; nos movemos 4 posiciones en el buffer de destino.
	mov ebx,[codigo] ; recuperamos el codigo para quedarnos con los bits sobrantes
	
	mov dword [bits_disponibles],32
	sub [bits_disponibles],ecx	; 32 menos los bits que nos sobraron.
	
	mov eax,ecx 	; pongo en eax los bits que sobraron para poder usar el shl con cl 
	mov ecx,32
	sub ecx,eax	; nos quedamos con 32 menos los bits que sobraron que son los que hay que shiftear.
	shl ebx,cl	; dejamos en la parte alta de ebx los bits sobrantes.
	

	
_continuar: 
	
	;inc byte proxSimbolo; apunto al siguiente simbolo
	inc dword [proxSimbolo]
	dec esi
	jmp _recorrer_src_buf

_volcarUltimosBits:
	cmp dword [bits_disponibles],32
	je fin
	bswap ebx	; Invertimos para que nos respete el orden de los bits
	mov [edi],ebx
	

fin:
	
	pop edi
	pop esi
	pop ebx
	leave
	ret